package com.zfei.gfb.controller;


import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.zfei.gfb.GfbService;
import com.zfei.gfb.api.StatsService;
import com.zfei.gfb.api.domain.StatsTag;
import com.zfei.gfb.api.domain.StatsValue;
import com.zfei.gfb.bean.Const;
import com.zfei.gfb.bean.Status;
import com.zfei.gfb.bean.StatusException;
import com.zfei.gfb.core.Auth;
import com.zfei.gfb.core.HttpJson;
import com.zfei.gfb.core.LogResult;
import com.zfei.gfb.dao.GfbGoodsMapper;
import com.zfei.gfb.dao.GfbOrderMapper;
import com.zfei.gfb.dao.GfbVillagerMapper;
import com.zfei.gfb.device.AppContext;
import com.zfei.gfb.model.GfbGoods;
import com.zfei.gfb.model.GfbOrder;
import com.zfei.gfb.model.GfbVillager;
import com.zfei.gfb.query.GfbGoodsQuery;
import com.zfei.gfb.query.h5.H5GoodsQuery;
import com.zfei.gfb.query.h5.H5MyGoodsQuery;
import com.zfei.gfb.request.*;
import com.zfei.gfb.util.Beans;
import com.zfei.gfb.util.Gsons;
import com.zfei.gfb.util.Now;
import com.zfei.gfb.util.gson.Types;
import com.zfei.gfb.vo.GfbGoodsListVo;
import com.zfei.gfb.vo.GfbGoodsVo;
import com.zfei.gfb.vo.GfbMyGoodsListVo;
import com.zfei.gfb.vo.GfbOrderVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author fgh
 * @version 1.0
 */

@Api(tags = "H5物品接口")
@RestController
@RequestMapping("/h5/goods")
public class H5GoodsController {

    @Resource
    private GfbService gfbService;

    @Resource
    private GfbGoodsMapper gfbGoodsMapper;

    @Resource
    private GfbOrderMapper gfbOrderMapper;

    @Resource
    private HttpSession httpSession;

    @Resource
    private StatsService statsService;

    @Resource
    private GfbVillagerMapper gfbVillagerMapper;

    @Auth(type = Const.VILLAGER)
    @ApiOperation(value = "物品发布")
    @ApiResponses({
            @ApiResponse(code = 200, message = "", response = GfbGoodsVo.class),
    })
    @LogResult
    @HttpJson("/add")
    public Object add(@RequestBody GfbGoodsAddRequest request) {

        request.checkInsertNull();
        GfbGoods record = Beans.copy(request, GfbGoods.class);

        GfbVillager villager = (GfbVillager) httpSession.getAttribute(AppContext.SESSION_H5_VILLAGER);

        record.setImages(Gsons.toJson(request.getImages()));
        record.setUserId(villager.getId());
        record.setVillagerName(villager.getVillagerName());
        record.setStatus(Const.GOOD_ON);
        record.setPubTime(Now.millis());
        record.setCreateTime(Now.millis());
        record.setUpdateTime(Now.millis());
        record.setCntime(DateUtil.now());

        gfbGoodsMapper.insertSelective(record);
        GfbGoodsVo vo = Beans.copy(record, GfbGoodsVo.class);
        return vo;
    }

    @Auth(type = Const.VILLAGER)
    @ApiOperation(value = "我发布的物品")
    @ApiResponses({
            @ApiResponse(code = 200, message = "", response = GfbGoodsListVo.class),
    })
    @LogResult
    @HttpJson("/my/list")
    public Object listMy(@RequestBody GfbGoodsQuery query) {
        query.build(Now::millis);

        GfbVillager villager = (GfbVillager) httpSession.getAttribute(AppContext.SESSION_H5_VILLAGER);
        query.setUserId(villager.getId());
        List<GfbGoods> records = gfbGoodsMapper.list(query);

        List<GfbGoodsVo> vos = new ArrayList<>();
        for (GfbGoods item : records) {
            GfbGoodsVo vo = Beans.copy(item, GfbGoodsVo.class);
            List<String> images = Gsons.fromJson(item.getImages(), Types.StringListType);

            vo.setImages(images);
            vos.add(vo);
        }

        GfbGoodsListVo result = new GfbGoodsListVo();
        result.setData(vos);

        return result;
    }


    @ApiOperation(value = "物品详情")
    @ApiResponses({
            @ApiResponse(code = 200, message = "", response = GfbGoodsVo.class),
    })
    @LogResult
    @HttpJson("/get")
    public Object get(@RequestBody GfbGetRequest request) {
        request.checkGetNull();
        Integer id = request.getId();

        GfbGoods record = gfbGoodsMapper.selectByPrimaryKey(id);

        GfbGoodsVo vo = Beans.copy(record, GfbGoodsVo.class);
        List<String> images = Gsons.fromJson(record.getImages(), Types.StringListType);
        vo.setImages(images);
        Integer userId = record.getUserId();
        GfbVillager goodsOwner = gfbVillagerMapper.selectByPrimaryKey(userId);
        vo.setOwner(goodsOwner == null ? null : goodsOwner.getName());

        boolean canBuy = false;
        if (httpSession.getAttribute(AppContext.SESSION_H5_VILLAGER) != null) {
            GfbVillager villager = (GfbVillager) httpSession.getAttribute(AppContext.SESSION_H5_VILLAGER);
            if (ifCanBuy(record, villager)) {
                canBuy = true;
            }
        }

        StatsValue postStats = new StatsValue(record.getId().toString(), StatsTag.GOODS_BROWSE_COUNT, 1);
        statsService.inc(postStats);

        //浏览量
        vo.setBrowseNum(statsService.get(record.getId().toString(), StatsTag.GOODS_BROWSE_COUNT).getNum());

        vo.setCanBuy(canBuy);

        return vo;
    }

    private boolean ifCanBuy(GfbGoods record, GfbVillager villager) {
        return record.getVillagerName().equals(villager.getVillagerName()) && !record.getUserId().equals(villager.getId());
    }

    @Auth(type = Const.VILLAGER)
    @ApiOperation(value = "上/下架")
    @LogResult
    @HttpJson("/my/set")
    public Object setMy(@RequestBody GfbSetRequest request) {
        request.checkSetNull(Const::legalGoodsSetStatus);

        Integer id = request.getId();
        Integer status = request.getStatus();

        GfbGoods record = gfbGoodsMapper.selectByPrimaryKey(id);
        if (record == null) {
            throw new StatusException(Status.NOT_EXIST);
        }
        if (request.getStatus() == Const.GOOD_OFF) {
            if (record.getStatus() != Const.GOOD_ON) {
                throw new StatusException(Status.INVALID_ARGUMENT);
            }
        }
        if (request.getStatus() == Const.GOOD_ON) {
            if (record.getStatus() != Const.GOOD_OFF) {
                throw new StatusException(Status.INVALID_ARGUMENT);
            }
            record.setPubTime(Now.millis());
        }
        if (request.getStatus() == Const.GOOD_DEAL) {
            if (record.getStatus() != Const.GOOD_ON) {
                throw new StatusException(Status.INVALID_ARGUMENT);
            }
        }
        if (request.getStatus() == Const.GOOD_COMPLETED) {
            throw new StatusException(Status.INVALID_ARGUMENT);
//            if(record.getStatus() != Const.GOOD_DEAL){
//                throw new StatusException(Status.INVALID_ARGUMENT);
//            }
        }

        record.setStatus(status);
        record.setUpdateTime(Now.millis());
        gfbGoodsMapper.updateByPrimaryKeySelective(record);

        return null;
    }


    @ApiOperation(value = "物品列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "物品列表", response = GfbGoodsListVo.class),
    })
    @LogResult
    @HttpJson("/list")
    public Object list(@RequestBody H5GoodsQuery query) {
        query.build(Now::millis);
        GfbGoodsListVo result = new GfbGoodsListVo();
        int total = gfbGoodsMapper.totalH5(query);
        result.setTotal(total);
        if (total == 0) {
            result.setData(Lists.newArrayList());
            return result;
        }
        List<GfbGoods> records = gfbGoodsMapper.listH5(query);

        List<GfbGoodsVo> vos = new ArrayList<>();
        for (GfbGoods item : records) {
            GfbGoodsVo vo = Beans.copy(item, GfbGoodsVo.class);
            List<String> images = Gsons.fromJson(item.getImages(), Types.StringListType);
            vo.setBrowseNum(statsService.get(item.getId().toString(), StatsTag.GOODS_BROWSE_COUNT).getNum());

            vo.setImages(images);
            vos.add(vo);
        }


        result.setData(vos);

        return result;
    }


    @Auth(type = Const.VILLAGER)
    @ApiOperation(value = "我购买的物品")
    @ApiResponses({
            @ApiResponse(code = 200, message = "", response = GfbMyGoodsListVo.class),
    })
    @LogResult
    @HttpJson("/listMyBuy")
    public Object listMyBuy(@RequestBody H5MyGoodsQuery query) {
        query.build(Now::millis);

        GfbMyGoodsListVo result = new GfbMyGoodsListVo();

        GfbVillager villager = (GfbVillager) httpSession.getAttribute(AppContext.SESSION_H5_VILLAGER);
        query.setUserId(villager.getId());

        List<GfbOrder> records = gfbOrderMapper.listH5(query);
        if (records.size() == 0) {
            return Lists.newArrayList();
        }

        List<Integer> goodsIds = records.stream().map(GfbOrder::getGoodsId).collect(Collectors.toList());
        List<GfbGoods> goodsList = gfbGoodsMapper.selectByIds(goodsIds);
        result.setGoods(goodsList);

        List<GfbOrderVo> vos = new ArrayList<>();
        for (GfbOrder item : records) {
            GfbOrderVo vo = Beans.copy(item, GfbOrderVo.class);
            List<String> images = Gsons.fromJson(item.getGoodsImages(), Types.StringListType);

            vo.setGoodsImages(images);
            vos.add(vo);
        }
        result.setOrderList(vos);

        return result;

    }


    @Auth(type = Const.VILLAGER)
    @ApiOperation(value = "确认付款")
    @ApiResponses({
            @ApiResponse(code = 200, message = "订单id，核销url拼接", response = String.class),
    })
    @LogResult
    @HttpJson("/pay")
    public Object pay(@RequestBody GfbOrderRequest request) {
        request.checkInsertNull();

        GfbVillager villager = (GfbVillager) httpSession.getAttribute(AppContext.SESSION_H5_VILLAGER);

        GfbGoods goods = gfbGoodsMapper.selectByPrimaryKey(request.getGoodsId());
        if (goods == null) {
            throw new StatusException(Status.NOT_EXIST);
        }
        if (goods.getUserId().equals(villager.getId())) {
            throw new StatusException(Status.UNAVAILABLE, "不能购买自己的物品");
        }

        if (goods.getStatus() != Const.GOOD_ON) {
            throw new StatusException(Status.STATUS_ERROR, "商品未上架");
        }
        if (!ifCanBuy(goods, villager)) {
            throw new StatusException(Status.BANNED, "本村人可买");
        }

        if (goods.getSaleType() != Const.SALE_TYPE_ON) {
            throw new StatusException(Status.STATUS_ERROR, "非工分交易物品");
        }

        //工分余额校验
        if (villager.getSourceUserId() == null) {
            throw new StatusException(Status.NOT_EXIST, "村民未认证");
        }
        int balance = gfbService.balance(villager.getSourceUserId());
        if (balance < goods.getPrice()) {
            throw new StatusException(Status.NOT_ENOUGH);
        }

        GfbOrder order = gfbService.order(villager, goods);

        gfbService.reduce(villager.getSourceUserId(), order.getPrice());
        return order.getId();

    }

    @ApiOperation(value = "扫码核销")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = String.class),
    })
    @LogResult
    @GetMapping("/writeOff")
    public Object writeOff(@RequestParam String orderId) {
        if (orderId == null) {
            throw new StatusException(Status.INVALID_ARGUMENT);
        }

        GfbOrder gfbOrder = gfbOrderMapper.selectByOrderId(orderId);
        if (gfbOrder == null) {
            throw new StatusException(Status.NOT_EXIST);
        }
        if (gfbOrder.getStatus() != Const.GOOD_DEAL) {
            throw new StatusException(Status.STATUS_ERROR, "商品未出售");
        }
        Integer goodsId = gfbOrder.getGoodsId();
        GfbGoods goods = gfbGoodsMapper.selectByPrimaryKey(goodsId);

        if (goods.getSaleType() != Const.SALE_TYPE_ON) {
            throw new StatusException(Status.STATUS_ERROR, "非工分交易物品");
        }

        gfbService.writeOffOrder(gfbOrder, goods);

        Integer userId = goods.getUserId();
        GfbVillager villager = gfbVillagerMapper.selectByPrimaryKey(userId);
        if (villager == null) {
            throw new StatusException(Status.NO_USER, "物品所属村民不存在【脏数据】");
        }
        if (villager.getSourceUserId() == null) {
            throw new StatusException(Status.NOT_EXIST, "村民未认证");
        }

        // 增加工分
        gfbService.recharge(villager.getSourceUserId(), gfbOrder.getPrice());
        return "success";

    }
}
